package org.xm.sk.controller.dbase;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestOperations;
import org.xm.sk.common.Arith;
import org.xm.sk.common.ToolsUtil;
import org.xm.sk.common.WxPayUtil;
import org.xm.sk.common.XmlProcessor;
import org.xm.sk.exception.BaseException;
import org.xm.sk.exception.DataNotFoundException;
import org.xm.sk.exception.RequestParamterException;
import org.xm.sk.exception.WxAuthException;
import org.xm.sk.module.IdBitWorker;
import org.xm.sk.service.data.BaseService;
import org.xm.sk.service.security.XmUser;
import org.xm.sk.vo.Base;
import org.xm.sk.vo.e.BoderStatus;
import org.xm.sk.vo.e.CouponStatus;
import org.xm.sk.vo.e.Datalevel;
import org.xm.sk.vo.ob.Boder2User;
import org.xm.sk.vo.ob.BoderPaid;
import org.xm.sk.vo.ob.CmBoder4Hairdresser;
import org.xm.sk.vo.ob.Ids;
import org.xm.sk.vo.ob.MapList;
import org.xm.sk.vo.ob.PageConf;
import org.xm.sk.vo.ob.Payarg;
import org.xm.sk.vo.ob.Payment;
import org.xm.sk.vo.ob.Paynotify;
import org.xm.sk.vo.ob.Performance;
import org.xm.sk.vo.ob.PostBoder;
import org.xm.sk.vo.ob.Prepay;
import org.xm.sk.vo.ob.ResultMsg;
import org.xm.sk.vo.ob.UnBoder4Hairdresser;
import org.xm.sk.vo.ob.WxMsgTemplate;
import org.xm.sk.vo.ob.WxMsgTemplateParam;
import org.xm.sk.vo.tb.Boder;
import org.xm.sk.vo.tb.Brand;
import org.xm.sk.vo.tb.Coupon;
import org.xm.sk.vo.tb.Hairdresser;
import org.xm.sk.vo.tb.Item;
import org.xm.sk.vo.tb.Price;
import org.xm.sk.vo.tb.ServerTime;
import org.xm.sk.vo.tb.Shop;
import org.xm.sk.vo.tb.User;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.annotations.ApiIgnore;

@SuppressWarnings("unchecked")
@Slf4j
@Api(tags = { "order" })
@RestController
@RequestMapping(value="/orders")
public class OrderController {
    
    @Value("${wx.login.cl.appId}")
    private String cl_appId;
    @Value("${wx.login.cl.secret}")
    private String cl_secret;
    @Value("${wx.pay.cl.key}")
    private String cl_key;
    @Value("${wx.pay.cl.mchId}")
    private String cl_mchId;
    @Value("${wx.pay.mkOrderUrl}")
    private String mkOrderUrl;
    @Value("${wx.pay.notifyUrl}")
    private String wxPayNotifyUrl;
    @Value("${wx.login.getAccessTokenUrl}")
    private String getAccessTokenUrl;
    @Value("${wx.login.postMsgUrl}")
    private String postMsgUrl;
    @Value("${wx.login.cl.templateId}")
    private String templateId;
    
    @Autowired
    private MessageSource messages;
    @Autowired
    private BaseService<Boder> boderService;
    @Autowired
    private BaseService<User> userService;
    @Autowired
    private BaseService<Item> itemService;
    @Autowired
    private BaseService<Price> priceService;
    @Autowired
    private BaseService<Hairdresser> hairdresserService;
    @Autowired
    private BaseService<Shop> shopService;
    @Autowired
    private BaseService<Coupon> couponService;
    @Autowired
    private IdBitWorker idBitWorker;
    @Autowired
    private XmlProcessor xmlProcessor;
    @Autowired
    private RestOperations restOperations;
    
    @ApiOperation(value="创建订单", notes="根据boder对象创建订单，使用此接口需要ADMIN权限")
    @ApiImplicitParam(name = "boder", value = "订单详细实体boder", required = true, dataType = "Boder")
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value="", method=RequestMethod.POST)
    public ResultMsg add(@RequestBody Boder boder) throws RequestParamterException {
        Boder u = null;
        if (null != boder.getId() && 0 < boder.getId())
            u = (Boder) boderService.findById(boder.getId());
        else
            u = boder;
        u.setCoupon(null);
        u.setCouponnum(null);
        u.setShop(null);
        u.setShopName(null);
        u.setHairdresser(null);
        u.setHairdresserName(null);
        u.setUser(null);
        u.getItems().clear();
        u.getPrices().clear();
        u.setName(boder.getName());
        u.setAddress(boder.getAddress());
        u.setMktime(boder.getMktime());
        u.setName(boder.getName());
        u.setPay(boder.getPay());
        u.setPhone(boder.getPhone());
        u.setPytime(boder.getPytime());
        u.setStatus(boder.getStatus());
        u.setSvtime(boder.getSvtime());
        if (null != boder.getCouponId() && 0 < boder.getCouponId()) {
            Coupon coupon = (Coupon) couponService.findById(boder.getCouponId());
            if (Base.isValid(coupon)) {
                u.setCoupon(coupon);
                u.setCouponnum(coupon.getCouponnum());
                u.setCouponValue(coupon.getActivity().getPrice());
            }
        }
        if (null != boder.getShopId() && 0 < boder.getShopId()) {
            Shop Shop = (Shop) shopService.findById(boder.getShopId());
            if (Base.isValid(Shop)) {
                u.setShop(Shop);
                u.setShopName(Shop.getName());
            }
        }
        if (null != boder.getHairdresserId() && 0 < boder.getHairdresserId()) {
            Hairdresser hairdresser = (Hairdresser) hairdresserService.findById(boder.getHairdresserId());
            if (Base.isValid(hairdresser)) {
                if (hairdresser.getShop().getId().intValue() != u.getShop().getId().intValue())
                    throw new RequestParamterException("指定的发型师不在指定的门店工作");
                u.setHairdresser(hairdresser);
                u.setHairdresserName(hairdresser.getName());
            }
        }
        if (null != boder.getUserId() && 0 < boder.getUserId()) {
            User User = (User) userService.findById(boder.getUserId());
            if (Base.isValid(User)) {
                u.setUser(User);
            }
        }
        String itemNames = null;
        Double priceValue = 0.00;
        Double brokerage = 0.00;
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("itemIds", new ArrayList<Integer>(boder.getItemIds()));
        map.put("hairdressId", boder.getHairdresserId());
        List<Price> priceList = (List<Price>) priceService
                .findAllByPage(new PageConf(-1, 0), map);
        if (priceList.isEmpty()) {
            throw new RequestParamterException("指定的项目ID、发型师ID和门店ID找到项目价格配置");
        }
        for (Price pr : priceList) {
            priceValue = Arith.add(priceValue, pr.getPrice());
            brokerage = Arith.add(brokerage, Arith.mul(pr.getPrice(), pr.getBrokerage()));
            u.getPrices().add(pr);
            u.getItems().add(pr.getItem());
            if (null == itemNames)
                itemNames = pr.getItem().getName();
            else
                itemNames = itemNames + "," + pr.getItem().getName();
        }
        u.setItemNames(itemNames);
        u.setPriceValue(priceValue);
        u.setBrokerage(brokerage);
        if (null != u.getId() && 0 < u.getId())
            boderService.update(u);
        else {
            u.setOrdernum(idBitWorker.nextOrderNum());
            boderService.add(u);
        }
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="删除订单", notes="根据URI的id来指定删除对象")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int")
    @PreAuthorize("hasAnyRole('ADMIN')")
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public ResultMsg delete(@PathVariable Integer id) {
        boderService.delete(id);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    @ApiOperation(value="删除订单", notes="根据POST的id列表来指定删除对象，可批量")
    @ApiImplicitParam(name = "ids", value = "订单ID集", required = true, dataType = "Ids")
    @RequestMapping(value="/delete", method=RequestMethod.DELETE)
    public ResultMsg Batchdelete(@RequestBody Ids ids) {
        boderService.delete(ids.getIds());
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="更新订单详细信息", notes="根据URI的id来指定更新对象，并根据传过来boder信息来更新订单详细信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "boder", value = "待更新的订单详细实体boder", required = true, dataType = "Boder")
    })
    @PreAuthorize("hasAnyRole('ADMIN') || hasPermission(#id, 'selfOrderById')")
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public ResultMsg update(@PathVariable Integer id, @RequestBody Boder boder) throws DataNotFoundException {
        boder.setId(id);
        boderService.update(boder);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="获取订单详细信息", notes="根据URI的id来获取订单详细信息")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int")
    @PreAuthorize("hasAnyRole('ADMIN') || hasPermission(#id, 'selfOrderById')")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public Boder load(@PathVariable Integer id) throws DataNotFoundException {
        Boder u = (Boder) boderService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(Boder.class.getName());
        }
        return u;
    }
    
    @ApiOperation(value="获取订单列表", notes="根据提交的分页信息列出所以订单信息")
    @ApiImplicitParam(name = "pageConf", value = "分页信息实体", required = true, dataType = "PageConf")
    @RequestMapping(value={"/list"}, method=RequestMethod.POST)
    public MapList<Boder> list(@RequestBody PageConf pageConf) {
        List<Boder> u = null;
        Long allCount = null;
        Object[] os = (Object[]) boderService.findAllByPage(pageConf);
        if (os[0] instanceof Page) {
            allCount = ((Page<Boder>) os[0]).getTotalElements();
            u = ((Page<Boder>) os[0]).getContent();
        } else {
            allCount = (long) ((List<Boder>) os[0]).size();
            u = (List<Boder>) os[0];
        }
        for (Boder c : u) {
            if (null != c.getShop())
                c.setShopId(c.getShop().getId());
            if (null != c.getHairdresser())
                c.setHairdresserId(c.getHairdresser().getId());
            if (null != c.getUser()) {
                c.setUserId(c.getUser().getId());
                if (null != c.getUser().getNickname()
                        && 0 < c.getUser().getNickname().trim().length()
                        && null != c.getUser().getPhone()
                        && 0 < c.getUser().getPhone().trim().length())
                    c.setUserName(c.getUser().getNickname() + ":"
                            + c.getUser().getPhone());
                else if (null != c.getUser().getPhone()
                        && 0 < c.getUser().getPhone().trim().length())
                    c.setUserName(c.getUser().getPhone());
                else if (null != c.getUser().getNickname()
                        && 0 < c.getUser().getNickname().trim().length())
                    c.setUserName(c.getUser().getNickname());
                else
                    c.setUserName(c.getUser().getName());
            }
            if (null != c.getCoupon())
                c.setCouponId(c.getCoupon().getId());
            if (null != c.getItems() && !c.getItems().isEmpty())
                for (Item p : c.getItems()) {
                    c.getItemIds().add(p.getId());
                }
            if (null != c.getPrices() && !c.getPrices().isEmpty())
                for (Price p : c.getPrices()) {
                    c.getPriceIds().add(p.getId());
                }
        }
        Double sumPrice = (Double) os[1];
        sumPrice = null == sumPrice ? 0.00 : sumPrice;
        Double sumBrokerage = (Double) os[2];
        Double sumPay = (Double) os[3];
        Double couponValue = (Double) os[4];
        sumBrokerage = null == sumBrokerage ? 0.00 : sumBrokerage;
        sumPay = null == sumPay ? 0.00 : sumPay;
        couponValue = null == couponValue ? 0.00 : couponValue;
        MapList<Boder> ml = new MapList<Boder>(allCount, u);
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("sumPrice", Double.parseDouble(String.format("%.2f", sumPrice)));
        map.put("sumBrokerage", Double.parseDouble(String.format("%.2f", sumBrokerage)));
        map.put("sumPay", Double.parseDouble(String.format("%.2f", sumPay)));
        map.put("couponValue", Double.parseDouble(String.format("%.2f", couponValue)));
        ml.setMapData(map);
        return ml;
    }

    // --------------------- 业务具体接口 ---------------------
    
    @ApiOperation(value="获取待评论订单列表", notes="根据提交的分页信息列出顾客所有待评论订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/paid/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<BoderPaid> listBoderPaid(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.METE);
        Page<BoderPaid> boderPaid = (Page<BoderPaid>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boderPaid.getTotalElements();
        return new MapList<BoderPaid>(allCount, boderPaid.getContent());
    }
    
    @ApiOperation(value="获取已评论订单列表", notes="根据提交的分页信息列出顾客所有已评论订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/meted/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<BoderPaid> listBoderMeted(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.METED);
        Page<BoderPaid> boderPaid = (Page<BoderPaid>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boderPaid.getTotalElements();
        return new MapList<BoderPaid>(allCount, boderPaid.getContent());
    }

    @ApiOperation(value="待评论订单删除", notes="根据URI的id指定待评论订单执行删除")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int")
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/nomete/{id}"}, method=RequestMethod.DELETE)
    public ResultMsg nomete(@PathVariable Integer id) throws BaseException {
        Boder u = (Boder) boderService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(Boder.class.getName());
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (null != u.getUser() && !Integer.valueOf(xmUser.getUserid()).equals(u.getUser().getId())) {
            throw new AccessDeniedException("无权限访问数据");
        }
        if (u.getStatus() != BoderStatus.METE) {
            throw new BaseException("此信息不是待评论订单");
        }
        u.setStatus(BoderStatus.NOMETE);
        boderService.update(u);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiOperation(value="预约下单", notes="根据postBoder对象创建订单")
    @ApiImplicitParam(name = "postBoder", value = "订单详细实体postBoder", required = true, dataType = "PostBoder")
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value="/mader", method=RequestMethod.POST)
    public PostBoder mkoder(@RequestBody PostBoder postBoder) throws RequestParamterException {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        User user = (User) userService.findById(xmUser.getUserid());
        if (null == user || Datalevel.NORMAL != user.getDatalevel()) {
            throw new AccessDeniedException("无效令牌信息，查无用户信息");
        }
        if (null == postBoder.getHairdressId()
                || 0 >= postBoder.getHairdressId().intValue()
                || null == postBoder.getItemIds()
                || postBoder.getItemIds().isEmpty()
                || null == postBoder.getMkTime()) {
            throw new RequestParamterException();
        }
        Date c = new Date();
        Boder boder = new Boder();
        if (null == postBoder.getPhone()) {
            postBoder.setPhone(xmUser.getPhone());
        }
        if (null == postBoder.getPhone()) {
            throw new RequestParamterException("无手机号");
        }
        Hairdresser hairdresser = (Hairdresser) hairdresserService.findById(postBoder.getHairdressId());
        if (null == hairdresser) {
            throw new RequestParamterException("查无发型师信息");
        }
        if (postBoder.getMkTime().getTime() <= (new Date()).getTime())
            throw new RequestParamterException("无效预约时间，预约时间只能大于当前时间");
        String date = new SimpleDateFormat("yyyy-MM-dd").format(postBoder.getMkTime());
        String time = (new SimpleDateFormat("yyyy-MM-dd HH:mm").format(postBoder.getMkTime())).replaceAll(date + " ", "");
        Set<ServerTime> stimes = hairdresser.getServerTimes();
        boolean nh = true;
        for (ServerTime st : stimes) {
            if (st.getName().equals(time)) {
                nh = false;
                break;
            }
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("hairdresserid", postBoder.getHairdressId());
        map.put("mktime", postBoder.getMkTime());
        Long ext = (Long) boderService.findAllByPage(null, map);
        if (null != ext && 0 != ext || nh)
            throw new RequestParamterException("无效预约时间，当前发型师无法提供该时间点的预约");
        map.clear();
        map.put("itemIds", new ArrayList<Integer>(postBoder.getItemIds()));
        map.put("hairdressId", postBoder.getHairdressId());
        List<Price> priceList = (List<Price>) priceService.findAllByPage(new PageConf(-1, 0), map);
        if (priceList.isEmpty()) {
            throw new RequestParamterException("指定的项目ID、发型师ID和门店ID找到项目价格配置");
        }
        Double price = 0.0;
        Double brokerage = 0.0;
        for (Integer itemId : postBoder.getItemIds()) {
            boolean has = false;
            for (Price pr : priceList) {
                if (pr.getItem().getId().intValue() == itemId) {
                    has = true;
                    price = Arith.add(price, pr.getPrice());
                    brokerage = Arith.add(brokerage, Arith.mul(pr.getPrice(), pr.getBrokerage()));
                    break;
                }
            }
            if (!has) {
                throw new RequestParamterException("存在指定项目无对应发型师的价格配置信息：" + itemId);
            }
        }
        map.clear();
        map.put("ids", new ArrayList<Integer>(postBoder.getItemIds()));
        List<Item> items = (List<Item>) itemService.findAllByPage(null, map);
        String itemNames = "";
        Set<String> itemNs = new HashSet<String>(0);
        for (Item i : items) {
            itemNames += i.getName() + ",";
            itemNs.add(i.getName());
        }
        if (0 < itemNames.length()) {
            itemNames = itemNames.substring(0, itemNames.length() - 1);
        }
        boder.setAddress(hairdresser.getShop().getAddress());
        boder.setBrokerage(brokerage);
        boder.setCreatedate(c);
        boder.setHairdresser(hairdresser);
        boder.setHairdresserName(hairdresser.getName());
        boder.setItems(new HashSet<Item>(items));
        boder.setItemNames(itemNames);
        boder.setMktime(postBoder.getMkTime());
        boder.setModifydate(c);
        boder.setPhone(postBoder.getPhone());
        boder.setOrdernum(idBitWorker.nextOrderNum());
        boder.setPrices(new HashSet<Price>(priceList));
        boder.setPriceValue(price);
        boder.setShop(hairdresser.getShop());
        boder.setShopName(hairdresser.getShop().getName());
        boder.setStatus(BoderStatus.PAYING);
        boder.setUser(user);
        boder = boderService.add(boder);
        postBoder.setId(boder.getId());
        postBoder.setOrdernum(boder.getOrdernum());
        postBoder.setShopId(hairdresser.getShop().getId());
        postBoder.setCreatedate(c);
        postBoder.setHairdressName(hairdresser.getName());
        postBoder.setItemNames(itemNs);
        postBoder.setPrice(price);
        if (null != hairdresser.getUser() && null != hairdresser.getUser().getImage())
            postBoder.setImageId(hairdresser.getUser().getImage().getId());
        postBoder.setShopName(hairdresser.getShop().getName());
        return postBoder;
    }

    @ApiIgnore()
    @ApiOperation(value="获取已预约订单列表", notes="根据提交的分页信息列出顾客已预约订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/making_x/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<Boder2User> listBoderMaking(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.SERVERING);
        Page<Boder2User> boder2User = (Page<Boder2User>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boder2User.getTotalElements();
        return new MapList<Boder2User>(allCount, boder2User.getContent());
    }

    @ApiOperation(value="取消未支付的订单", notes="根据URI的id指定取消已预约的订单")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int")
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/cancel/{id}"}, method=RequestMethod.DELETE)
    public ResultMsg cancelBoderMaking(@PathVariable Integer id) throws BaseException {
        Boder u = (Boder) boderService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(Boder.class.getName());
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (null != u.getUser() && !Integer.valueOf(xmUser.getUserid()).equals(u.getUser().getId())) {
            throw new AccessDeniedException("无权限访问数据");
        }
        if (u.getStatus().ordinal() > BoderStatus.PAYING.ordinal()) {
            throw new BaseException("此信息不是已预约订单");
        }
        u.setStatus(BoderStatus.CANCEL);
        boderService.update(u);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiOperation(value="获取已取消预约订单列表", notes="根据提交的分页信息列出顾客已取消预约订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/cancel/making/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<Boder2User> listCancelBoderMaking(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.CANCEL);
        Page<Boder2User> boder2User = (Page<Boder2User>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boder2User.getTotalElements();
        return new MapList<Boder2User>(allCount, boder2User.getContent());
    }
    
    @ApiOperation(value="客户端获取完成预约订单列表", notes="根据提交的分页信息列出顾客完成预约订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/maked/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<Boder2User> listBoderMaked(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.SERVERING);
        Page<Boder2User> boder2User = (Page<Boder2User>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boder2User.getTotalElements();
        return new MapList<Boder2User>(allCount, boder2User.getContent());
    }
    
    @ApiOperation(value="发型师端获取有关自己的未完成的订单列表", notes="根据提交的分页信息列出发型师未完成的订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE')")
    @RequestMapping(value={"/uc/hairdresser/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<UnBoder4Hairdresser> listUnBoder4Hairdresser(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (0 == xmUser.getHairdresserid()) {
            throw new RequestParamterException("当前用户非发型师用户，查无发型师信息");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("hairdresserid", xmUser.getHairdresserid());
        map.put("boderStatus", BoderStatus.SERVERING);
        Page<UnBoder4Hairdresser> boder2User = (Page<UnBoder4Hairdresser>) boderService.findAllByPage(new PageConf(page, size), map);
        for (UnBoder4Hairdresser b : boder2User) {
            if (null != b.getNickname()
                    && 0 < b.getNickname().trim().length()) {
                try {
                    b.setNickname(b.getNickname());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        Long allCount = boder2User.getTotalElements();
        return new MapList<UnBoder4Hairdresser>(allCount, boder2User.getContent());
    }
    
    @ApiOperation(value="发型师端获取有关自己的已完成的订单列表", notes="根据提交的分页信息列出发型师已完成的订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE')")
    @RequestMapping(value={"/cm/hairdresser/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<CmBoder4Hairdresser> listCmBoder4Hairdresser(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (0 == xmUser.getHairdresserid()) {
            throw new RequestParamterException("当前用户非发型师用户，查无发型师信息");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("hairdresserid", xmUser.getHairdresserid());
        map.put("boderStatus", BoderStatus.METE);
        Page<CmBoder4Hairdresser> boder2User = (Page<CmBoder4Hairdresser>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boder2User.getTotalElements();
        return new MapList<CmBoder4Hairdresser>(allCount, boder2User.getContent());
    }
    
    @ApiOperation(value="获取服务中的订单列表", notes="根据提交的分页信息列出顾客服务中的订单信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "size", value = "每页数量", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int", paramType = "path")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT')")
    @RequestMapping(value={"/servering/{size}/{page}"}, method=RequestMethod.GET)
    public MapList<Boder2User> listBoderServering(@PathVariable Integer size, @PathVariable Integer page) throws RequestParamterException {
        if (null == size || null == page || 1 > size || 0 > page) {
            throw new RequestParamterException();
        }
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userid", xmUser.getUserid());
        map.put("boderStatus", BoderStatus.SERVERING);
        Page<Boder2User> boder2User = (Page<Boder2User>) boderService.findAllByPage(new PageConf(page, size), map);
        Long allCount = boder2User.getTotalElements();
        return new MapList<Boder2User>(allCount, boder2User.getContent());
    }

    // 订单使用优惠券，重新计算应付价格
    // 订单发起支付
    @Transactional
    @ApiOperation(value="对服务中的订单发起支付(带优惠券码)", notes="根据URI的id对订单发起支付操作（服务中的订单不限于客户还在剪头发，可能剪完了要结账）")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int"),
        @ApiImplicitParam(name = "couponnum", value = "优惠券编号", required = true, paramType = "path", dataType = "string")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT') && hasPermission(#id, 'selfOrderById')")
    @RequestMapping(value={"/pay/{id}/{couponnum}"}, method=RequestMethod.GET)
    public Payarg payWithCouponnum(@PathVariable Integer id, @PathVariable String couponnum) throws RequestParamterException,
            JsonParseException, JsonMappingException, JsonProcessingException,
            IOException, WxAuthException {
        return pay(id, couponnum);
    }
    
    @Transactional
    @ApiOperation(value="对服务中的订单发起支付(不带优惠券码)", notes="根据URI的id对订单发起支付操作（服务中的订单不限于客户还在剪头发，可能剪完了要结账）")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int")
    })
    @PreAuthorize("hasAnyRole('ADMIN', 'CLIENT') && hasPermission(#id, 'selfOrderById')")
    @RequestMapping(value={"/pay/{id}"}, method=RequestMethod.GET)
    public Payarg payWithoutCouponnum(@PathVariable Integer id) throws RequestParamterException,
            JsonParseException, JsonMappingException, JsonProcessingException,
            IOException, WxAuthException {
        return pay(id, null);
    }

    public Payarg pay(Integer id, String couponnum) throws RequestParamterException,
            JsonParseException, JsonMappingException, JsonProcessingException,
            IOException, WxAuthException {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        User user = (User) userService.findById(xmUser.getUserid());
        if (null == user || Datalevel.NORMAL != user.getDatalevel()) {
            throw new AccessDeniedException("无效令牌信息，查无用户信息");
        }
        Payarg payarg = null;
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_NULL);
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        Boder u = (Boder) boderService.findById(id);
        String ordernum = u.getOrdernum();
        log.info("A-订单ID：{} 编号为：{} 进行支付", id, ordernum);
        Double priceValue = u.getPriceValue();
        Double pay = priceValue;
        if (null != u.getPay() && 0 < u.getPay()) {
            pay = u.getPay();
        } else {
            u.setPay(pay);
        }
        Coupon coupon = null;
        if (null != couponnum && 0 < couponnum.length()) {
            if (null != u.getCoupon()) {
                throw new RequestParamterException("此订单已具有优惠码，不可重复使用");
            } else {
                coupon = new Coupon();
                ToolsUtil.cleanDao4Query(coupon);
                coupon.setCouponnum(couponnum);
                User un = new User();
                ToolsUtil.cleanDao4Query(un);
                un.setId(user.getId());
                un.setName(user.getName());
                coupon.setUser(un);
                coupon.setUserName(user.getName());
                coupon.setStatus(CouponStatus.NORMAL);
                List<Coupon> list = (List<Coupon>) couponService
                        .findAll(coupon);
                if (null != list && !list.isEmpty()) {
                    coupon = list.get(0);
                    if (null != coupon.getActivity()) {
                        try {
                            SimpleDateFormat sdf = new SimpleDateFormat(
                                    "yyyy-MM-dd");
                            Date now = sdf.parse(sdf.format(new Date()));
                            if (null != coupon.getActivity().getStartline()) {
                                Date startline = sdf.parse(sdf.format(
                                        coupon.getActivity().getStartline()));
                                if (startline.getTime() > now.getTime())
                                    throw new RequestParamterException(
                                            "优惠券所属活动还未开始");
                            }
                            if (null != coupon.getActivity().getDeadline()) {
                                Date dealline = sdf.parse(sdf.format(
                                        coupon.getActivity().getDeadline()));
                                if (dealline.getTime() < now.getTime())
                                    throw new RequestParamterException(
                                            "优惠券所属活动已截至");
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    if (null != u.getShop() && null != u.getShop().getBrand()
                            && null != coupon.getActivity()
                            && null != coupon.getActivity().getBrands()
                            && !coupon.getActivity().getBrands().isEmpty()) {
                        boolean nohas = true;
                        for (Brand brand : coupon.getActivity().getBrands()) {
                            if (brand.getId()
                                    .equals(u.getShop().getBrand().getId())) {
                                nohas = false;
                                break;
                            }
                        }
                        if (nohas) {
                            throw new RequestParamterException(
                                    "优惠券不适用此订单所在门店在品牌消费");
                        }
                    }
                    if (null != coupon.getActivity()
                            && null != coupon.getActivity().getShops()
                            && !coupon.getActivity().getShops().isEmpty()) {
                        boolean nohas = true;
                        for (Shop shop : coupon.getActivity().getShops()) {
                            if (shop.getId().equals(u.getShop().getId())) {
                                nohas = false;
                                break;
                            }
                        }
                        if (nohas) {
                            throw new RequestParamterException("优惠券不适用此订单所在门店消费");
                        }
                    }
                    if (null != coupon.getActivity()
                            && null != coupon.getActivity().getItems()
                            && !coupon.getActivity().getItems().isEmpty()) {
                        boolean nohas = false;
                        for (Item it : u.getItems()) {
                            boolean nohas1 = true;
                            for (Item item : coupon.getActivity().getItems()) {
                                if (item.getId().equals(it.getId())) {
                                    nohas1 = false;
                                    break;
                                }
                            }
                            nohas = nohas || nohas1;
                            if (nohas) {
                                throw new RequestParamterException("优惠券不适用此订单所购买的服务项目消费");
                            }
                        }
                    }
                    if (null != coupon.getActivity()
                            && null != coupon.getActivity().getHairdresser()) {
                        if (u.getHairdresser().getId() != coupon.getActivity().getHairdresser().getId())
                            throw new RequestParamterException("优惠券不适用此订单所预约的发型师进行消费");
                    }
                    pay = priceValue - coupon.getActivity().getPrice();
                    u.setPay(pay);
                    u.setCoupon(coupon);
                    u.setCouponnum(coupon.getCouponnum());
                    u.setCouponValue(coupon.getActivity().getPrice());
                    coupon.setStatus(CouponStatus.USED);
                } else {
                    throw new RequestParamterException("无效优惠券码");
                }
            }
        } else if (null != u.getCoupon()) {
            coupon = u.getCoupon();
            coupon.setStatus(CouponStatus.USED);
        }
        int pv = (int) (pay * 100);
        if (null != u.getPrepayId() && 0 < u.getPrepayId().trim().length()) {
            payarg = new Payarg(cl_appId, WxPayUtil.createCode(10), "prepay_id=" + u.getPrepayId(), null, "MD5", (System.currentTimeMillis() + "").substring(0, 10));
            payarg.setSign(sign(payarg));
            log.info("X--订单ID：{} 编号为：{}，已做个微信支付下单，不需要重做！", id, u.getOrdernum());
            return payarg;
        }
        log.info("B-订单ID：{} 编号为：{} 进行支付，支付价格：{}，实付：{}，优惠券号：{}", id, ordernum, priceValue, pay, couponnum);
        if (0 < pay) {
            Payment payment = new Payment();
            payment.setAppid(cl_appId);
            payment.setAttach("SK美发客户端微信小程序订单支付");
            payment.setBody("SK美发小程序-订单微信支付");
            payment.setDetail(mapper.writeValueAsString(u));
            payment.setMch_id(cl_mchId);
            payment.setNonce_str(WxPayUtil.createCode(10));
            payment.setNotify_url(wxPayNotifyUrl);
            payment.setOpenid(xmUser.getUsername());
            payment.setOut_trade_no(ordernum);
            payment.setSpbill_create_ip(ToolsUtil.getIpAddr());
            payment.setTotal_fee(pv + "");
            payment.setTrade_type("JSAPI");
            payment.setSign(sign(payment));
            String xml = xmlProcessor.objectToXML(payment);
            xml = xml.replaceAll("<\\?.*\\?>\n", "").replaceAll(" xmlns:ns2=\"org.xm.sk\"", "").replace("ns2:payment-info", "xml");
            log.info("C--订单ID：{} 编号为：{}，提交给微信平台URL：{}，下单支付内容：{}", id, ordernum, mkOrderUrl, xml);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_XML);
            HttpEntity<String> request = new HttpEntity<String>(xml, headers);
            String result = restOperations.postForObject(mkOrderUrl, request, String.class);
            log.info("D--订单ID：{} 编号为：{}，微信下单返回结果：{}", id, ordernum, result);
            Prepay prepay = (Prepay) xmlProcessor.xmlToObject(result.replace("<xml>", "<ns2:prepay-info xmlns:ns2=\"org.xm.sk\">").replaceAll("</xml>", "</ns2:prepay-info>"));
            if (null != prepay.getReturnMsg() && !"OK".equals(prepay.getReturnMsg().trim())) {
                String info = prepay.getReturnMsg();
                if (null != prepay.getErrCodeDes() && 0 < prepay.getErrCodeDes().trim().length())
                    info = prepay.getErrCodeDes().trim();
                log.error("E--订单ID：{} 编号为：{}，微信下单失败！返回错误信息：{}", id, ordernum, info);
                throw new WxAuthException(info);
            } else if ("SUCCESS".equals(prepay.getReturnCode())) {
                log.info("F--订单ID：{} 编号为：{}，微信下单成功！START", id, ordernum);
                if (null != coupon)
                    couponService.update(coupon);
                u.setPrepayId(prepay.getPrepayId());
                boderService.update(u);
                payarg = new Payarg(cl_appId, WxPayUtil.createCode(10), "prepay_id=" + prepay.getPrepayId(), null, "MD5", (System.currentTimeMillis() + "").substring(0, 10));
                payarg.setSign(sign(payarg));
                log.info("F--订单ID：{} 编号为：{}，微信下单成功！END", id, ordernum);
                return payarg;
            } else {
                log.error("G--订单ID：{} 编号为：{}，微信下单异常！微信平台返回的信息无错误描述，但也无成功标识。", id, ordernum);
                throw new WxAuthException("微信支付服务异常！");
            }
        } else {
            log.info("H--订单ID：{} 编号为：{}，0元微信下单成功！START", id, ordernum);
            if (null != coupon)
                couponService.update(coupon);
            u.setPrepayId("wx0000000000000000000000000000000000");
            u.setBrokerage(0.0);
            u.setStatus(BoderStatus.SERVERING);
            u.setPytime(new Date());
            u.setVerificode(idBitWorker.getRandomNumCode(4));
            boderService.update(u);
            payarg = new Payarg(cl_appId, WxPayUtil.createCode(10), "prepay_id=wx0000000000000000000000000000000000", null, "MD5", (System.currentTimeMillis() + "").substring(0, 10));
            payarg.setSign(sign(payarg));
            log.info("H--订单ID：{} 编号为：{}，0元微信下单成功！END", id, ordernum);
            return payarg;
        }
    }
    
    @ApiOperation(value="获取微信平台支付结果消息", notes="根据提交的xml信息，对订单支付状态进行更新（注：此接口不做权限限制，即请求头部鉴权信息不用传")
    @ApiImplicitParams({
        @ApiImplicitParam(paramType = "header", dataType = "String", name = "authorization", defaultValue = "Bearer token", value = "令牌", required = false),
        @ApiImplicitParam(name = "xml", value = "微信平台支付通知XML信息", required = true, dataType = "string")
    })
    @RequestMapping(value={"/pay/notify"}, method=RequestMethod.POST)
    public String payNotify(@RequestBody String xml,
            HttpServletResponse response)
            throws RequestParamterException, IOException {
        String result = "<xml>\n\t<return_code><![CDATA[SUCCESS]]></return_code>\n\t<return_msg><![CDATA[OK]]></return_msg>\n</xml>";
        Paynotify notify = (Paynotify) xmlProcessor.xmlToObject(xml.replace("<xml>", "<ns2:paynotify-info xmlns:ns2=\"org.xm.sk\">").replaceAll("</xml>", "</ns2:paynotify-info>"));
        String ordernum = notify.getOutTradeNo();
        log.info("A-微信平台支付通知，系统订单号：{}", ordernum);
        Boder u = new Boder();
        ToolsUtil.cleanDao4Query(u);
        u.setOrdernum(ordernum);
        u.setStatus(BoderStatus.PAYING);
        List<Boder> list = (List<Boder>) boderService.findAll(u);
        if (null == list || list.isEmpty()) {
            log.error("B-微信平台支付通知，系统订单号：{}，系统查无状态合法的相关订单！", ordernum);
            return result.replace("SUCCESS", "FAIL").replaceAll("OK", "invalid out_trade_no");
        }
        u = list.get(0);
        if (null != notify.getReturnMsg() && 0 < notify.getReturnMsg().length()) {
            u.setMemo(notify.getReturnMsg());
        } else if ("SUCCESS".equals(notify.getReturnCode())) {
            Double brokerage = 0.0;
            for (Price pr : u.getPrices()) {
                brokerage = Arith
                        .add(brokerage,
                                Arith.mul(
                                        Arith.mul(
                                                Arith.div(pr.getPrice(),
                                                        u.getPriceValue()),
                                                u.getPay()),
                                        pr.getBrokerage()));
            }
            u.setBrokerage(brokerage);
            u.setStatus(BoderStatus.SERVERING);
            u.setPytime(new Date());
            u.setVerificode(idBitWorker.getRandomNumCode(4));
            u.setMemo(null);
        } else {
            u.setMemo("微信平台支付异常失败：收到支付结果通知信息，但无错误原因描述");
        }
        boderService.update(u);
        if (null != u.getMemo())
            log.error("C-微信平台支付通知，系统订单号：{}，支付失败！{}", ordernum, u.getMemo());
        else {
            log.info("D-微信平台支付通知，系统订单号：{}，通过微信平台支付完成！", ordernum);
            // 支付完成，推送消息
            try {
                WxMsgTemplate wxMsgTemplate = new WxMsgTemplate();
                wxMsgTemplate.setToUser(u.getUser().getName());
                wxMsgTemplate.setTemplateId(templateId);
                wxMsgTemplate.setFormId(u.getPrepayId());
                wxMsgTemplate.setUrl("");
                wxMsgTemplate.setTopColor("#00DD00");
                List<WxMsgTemplateParam> paras = new ArrayList<WxMsgTemplateParam>();
                paras.add(new WxMsgTemplateParam("keyword1", u.getOrdernum(), "#0044BB"));
                String userName = "尊敬的客户";
                if (null != u.getUser() && null != u.getUser().getNickname() && 0 < u.getUser().getNickname().length()) {
                    userName = u.getUser().getNickname();
                }
                paras.add(new WxMsgTemplateParam("keyword2", userName, "#0044BB"));
                String shopName = "";
                if (null != u.getShop() && null != u.getShop().getName() && 0 < u.getShop().getName().length()) {
                    shopName = u.getShop().getName();
                }
                paras.add(new WxMsgTemplateParam("keyword3", shopName, "#0044BB"));
                String hairdresserName = "";
                if (null != u.getHairdresser() && null != u.getHairdresser().getName() && 0 < u.getHairdresser().getName().length()) {
                    hairdresserName = u.getHairdresser().getName();
                }
                paras.add(new WxMsgTemplateParam("keyword4", hairdresserName, "#0044BB"));
                String modifyDate = "";
                if (null != u.getModifydate()) {
                    modifyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(u.getModifydate());
                }
                paras.add(new WxMsgTemplateParam("keyword5", modifyDate, "#0044BB"));
                paras.add(new WxMsgTemplateParam("keyword6", u.getPay() + "", "#0044BB"));
                paras.add(new WxMsgTemplateParam("keyword7", u.getItemNames(), "#0044BB"));
                wxMsgTemplate.setTemplateParamList(paras);
                sendWxMsg(wxMsgTemplate);
            } catch (WxAuthException e) {
                log.error(e.getMessage());
                e.printStackTrace();
            }
        }
        return result;
    }
    
    public void sendWxMsg(WxMsgTemplate template) throws JsonParseException,
            JsonMappingException, IOException, WxAuthException {
        Map<?, ?> map = restOperations.getForObject(getAccessTokenUrl,
                HashMap.class, cl_appId, cl_secret);
        if (null != map.get("errmsg")) {
            throw new WxAuthException(map.get("errmsg").toString());
        }
        if (!map.containsKey("access_token")
                || null == map.get("access_token")) {
            throw new WxAuthException("微信小程序推送token信息获取异常！");
        }
        String accessToken = (String) map.get("access_token");
        map = restOperations.postForObject(postMsgUrl, template.toMap(),
                HashMap.class, accessToken);
        if (null != map.get("errmsg")) {
            throw new WxAuthException(map.get("errmsg").toString());
        }
    }

    @ApiOperation(value="发型师获取自己业绩统计情况", notes="根据URI所带地址路径不同，分别统计年、月、日的业绩情况(此接口只有管理员和发型师能用，而且必须有发型师相关信息，ymd:'year','month','day')")
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE')")
    @RequestMapping(value={"/performance/{ymd}"}, method=RequestMethod.GET)
    public List<Performance> performance(@PathVariable String ymd) throws RequestParamterException {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (0 == xmUser.getHairdresserid()) {
            throw new RequestParamterException("当前用户非发型师用户，查无发型师信息");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("hairdresserid", xmUser.getHairdresserid());
        if ("year".equals(ymd)) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.YEAR, -7);
            int year = cal.get(Calendar.YEAR);
            map.put("tag", "" + year);
        } else if ("month".equals(ymd)) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.MONTH, -7);
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            map.put("tag", year + "-" + month);
        } else if ("day".equals(ymd)) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -20);
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            int day = cal.get(Calendar.DATE);
            map.put("tag", year + "-" + month + "-" + day);
        }
        return (List<Performance>) boderService.findAllByPage(null, map);
    }
    
    // 发型师端接收预约操作
    @ApiIgnore()
    @ApiOperation(value="发型师接收预约订单", notes="根据URI所带订单id信息，发型师接收预约订单(此接口只有管理员和发型师能调用)")
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE') || hasPermission(#id, 'selfOrderById4Hairdresser_accept')")
    @RequestMapping(value={"/accept_x/{id}"}, method=RequestMethod.PUT)
    public ResultMsg acceptBoder(@PathVariable Integer id) {
        Boder boder = new Boder();
        boder.setId(id);
        boder.setStatus(BoderStatus.SERVERING);
        boderService.update(boder);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    // 发型师端服务订单操作
    @ApiOperation(value="发型师对订单开始服务", notes="根据URI所带订单id信息，发型师对订单开始服务(此接口只有管理员和发型师能调用)")
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE') || hasPermission(#id, 'selfOrderById4Hairdresser_server')")
    @RequestMapping(value={"/server/{id}"}, method=RequestMethod.PUT)
    public ResultMsg serverBoder(@PathVariable Integer id) throws RequestParamterException {
        if (null == id || 1 > id) {
            throw new RequestParamterException();
        }
        Boder boder = (Boder) boderService.findById(id);
        if (!Base.isValid(boder)) {
            throw new RequestParamterException("查无订单信息");
        }
        boder.setStatus(BoderStatus.SERVERING);
        boder.setSvtime(new Date());
        boderService.update(boder);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    protected String sign(Object obj) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_NULL);
        String jsonStr = mapper.writeValueAsString(obj);
        log.info(jsonStr);
        Map<String, String> map = mapper.readValue(jsonStr, Map.class);
        WxPayUtil.paraFilter(map);
        String signString = WxPayUtil.createLinkString(map);
        log.info("signString: " + signString);
        String sign = WxPayUtil.sign(signString, cl_key,
                StandardCharsets.UTF_8.name());
        log.info(sign);
        return sign;
    }

    // 发型师和商家核销订单
    @ApiOperation(value="商家端/发型师对订单核销", notes="根据URI所带订单id信息，商家端/发型师对订单核销(此接口只有管理员和发型师能调用)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "verificode", value = "核销码", required = true, paramType = "path", dataType = "string") })
    @PreAuthorize("hasAnyRole('ADMIN', 'BOSS', 'HAIRDRE') || hasPermission(#id, 'selfOrderById4Hairdresser_server')")
    @RequestMapping(value={"/verify/{id}/{verificode}"}, method=RequestMethod.PUT)
    public ResultMsg verifyBoder(@PathVariable Integer id, @PathVariable String verificode) throws RequestParamterException {
        if (null == id || 1 > id) {
            throw new RequestParamterException();
        }
        if (null == verificode || 4 > verificode.trim().length()) {
            throw new RequestParamterException("核销码参数错误");
        }
        Boder boder = (Boder) boderService.findById(id);
        if (!Base.isValid(boder)) {
            throw new RequestParamterException("查无订单信息");
        }
        if (BoderStatus.SERVERING != boder.getStatus())
            throw new RequestParamterException("当前订单不允核销");
        if (!verificode.equals(boder.getVerificode()))
            throw new RequestParamterException("此订单的核销码输入错误");
        boder.setStatus(BoderStatus.METE);
        boder.setSvtime(new Date());
        boderService.update(boder);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

}